package io.renren.ssh;

import com.alibaba.fastjson.JSONObject;
import com.jcraft.jsch.JSchException;
import io.renren.common.utils.DateUtils;
import io.renren.modules.sys.entity.SysUserTokenEntity;
import io.renren.modules.sys.service.ShiroService;
import io.renren.modules.systemconfig.entity.SystemConfigServersEntity;
import io.renren.modules.systemconfig.service.SysConfigServerService;
import lombok.extern.java.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Component
@ServerEndpoint("/sftp/{serverId}/{token}")
@Log
public class SFTPWebsocketServer {
    private static ApplicationContext applicationContext;
    public static void setApplicationContext(ApplicationContext applicationContext) {
        SFTPWebsocketServer.applicationContext = applicationContext;
    }

    private static Logger logger = LoggerFactory.getLogger(SFTPWebsocketServer.class);


    public static HashMap<String,SftpConnection> ServerId_SFTPConn =new HashMap<>();

    public static HashMap<String,String>   session_ServerId = new HashMap<>();

    private Session ConcurrentSession  = null;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "serverId") String serverId, @PathParam(value = "token") String token) {
        try {

            ShiroService shiroService=applicationContext.getBean(ShiroService.class);
            SysUserTokenEntity tokenEntity =  shiroService.queryByToken(token);
            if(token == null||tokenEntity==null||tokenEntity.getUserId()==null){
                SshResponse response = new SshResponse(1,"登录失败请重新登录！","/error");
                try{sendMessage(session, JSONObject.toJSONString(response));}catch (Exception e1){
                    e1.printStackTrace();
                }
                session.close();
            }

            Long userId=tokenEntity.getUserId();



            if(!ServerId_SFTPConn.containsKey(serverId+"-"+userId)){
                initSFTPConnect(serverId,serverId+"-"+userId);
            }
            List<FileAttri> files = null;
            try{
                files = ServerId_SFTPConn.get(serverId+"-"+userId).getSession().ls("/root",false,null);
            }catch (JSchException e){
                initSFTPConnect(serverId,serverId+"-"+userId);
                files = ServerId_SFTPConn.get(serverId+"-"+userId).getSession().ls("/root",false,null);
            }
            ConcurrentSession = session;
            ServerId_SFTPConn.get(serverId+"-"+userId).setPwd("/root");
            SftpResponse sr = new SftpResponse(0,"登录成功!\n服务器时间："+ DateUtils.formatDefault(new Date()),"/root",files);

            sendMessage(session, JSONObject.toJSONString(sr));
            session_ServerId.put(session.getId(),serverId+"-"+userId);
        } catch (Exception e) {
            e.printStackTrace();
            SshResponse response = new SshResponse(1,"服务器IO异常！","/error");
            try{sendMessage(session, JSONObject.toJSONString(response));}catch (Exception e1){
                e1.printStackTrace();
            }
        }
    }

    private void initSFTPConnect(String serverId,String key) throws Exception{
        SysConfigServerService sysConfigServerService=applicationContext.getBean(SysConfigServerService.class);
        SystemConfigServersEntity se = sysConfigServerService.getById(serverId);
        if(se!=null){
            System.out.println("se.getLoginName()"+se.getLoginName());
            System.out.println("se.getSshPwd()"+se.getSshPwd());
            SftpConnection  conn  = new SftpConnection(se.getLoginName(),se.getSshPwd(),se.getIpAddr(),20000);

            SFTPClient client = new SFTPClient(se);

//            ClientSession session = SshUtils.SSH_login(conn);
            conn.setSession(client);
            ServerId_SFTPConn.put(key,conn);
        }else{
            throw new SshTimeoutException("无法加载服务器信息!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(ConcurrentSession!=null&&ConcurrentSession.getId()!=null&&session_ServerId.containsKey(ConcurrentSession.getId())){
            SftpConnection conn = ServerId_SFTPConn.get(session_ServerId.get(ConcurrentSession.getId()));
            try{
                conn.getSession().close();
            }catch (Exception e){
                e.printStackTrace();
            }
            ServerId_SFTPConn.remove(session_ServerId.get(ConcurrentSession.getId()));
            session_ServerId.remove(ConcurrentSession.getId());
            logger.info("关闭 ssh 连接："+ conn.getHostname());

        }

        logger.info("连接关闭！");
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("收到来自窗口 {}  的信息:{}" ,session.getId(), message);
        try{
            SftpConnection conn = ServerId_SFTPConn.get(session_ServerId.get(session.getId()));
            message=message.replace("//","/");
            if("<--GOBACK-->".equals(message)){
                String pwd = conn.getPwd();
                if("\\".equals(pwd)||"/".equals(pwd)){

                }else{
                    String newpwd = pwd.substring(0,pwd.lastIndexOf('/'));
                    System.out.println("newpwd:"+newpwd);
                    if("".equals(newpwd)||newpwd==null){
                        newpwd="/";
                    }
                    List<FileAttri> files  = conn.getSession().ls(newpwd,false,null);
                    System.out.println("ssh返回:"+JSONObject.toJSONString(files));
                    conn.setPwd(newpwd);
                    SftpResponse sr = new SftpResponse(0,"",conn.getPwd(),files);
                    sendMessage(session, JSONObject.toJSONString(sr));
                }

            }else {
                List<FileAttri> files  = conn.getSession().ls(message,false,null);
                System.out.println("ssh返回:"+JSONObject.toJSONString(files));
                conn.setPwd(message);
                SftpResponse sr = new SftpResponse(0,"",conn.getPwd(),files);
                sendMessage(session, JSONObject.toJSONString(sr));
            }


        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误");
        error.printStackTrace();
    }
    public static void sendMessage(Session session,String message) throws IOException {
        log.info(message);
        session.getBasicRemote().sendText(message);
    }
}